import java.util.Random;
import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

/**
 * 加减法口算练习系统 V0.3
 * 功能：生成50道100以内的加减法算式习题，无重复算式，可控制加减法比例
 */
public class CalculationSystemV03 {
    
    /**
     * 主类入口
     */
    public static void main(String[] args) {
        System.out.println("欢迎使用加减法口算练习系统 V0.3");
        System.out.println("=================================");
        
        // 设置加减法比例（这里设置为60%加法，40%减法）
        double additionRatio = 0.6; // 加法比例为60%
        
        // 生成并显示50道无重复习题
        ExerciseGenerator generator = new ExerciseGenerator();
        Exercise[] exercises = generator.generateUniqueExercises(50, additionRatio);
        
        ExercisePrinter printer = new ExercisePrinter();
        printer.printExercisesWithAnswers(exercises);
        
        System.out.println("\n=================================");
        System.out.println("习题生成完成，包含答案！");
        System.out.println("特点：无重复算式，加法约占60%，减法约占40%");
    }
}

/**
 * 习题类：存储一道算术题及其相关信息
 */
class Exercise {
    private int firstNumber;    // 第一个操作数
    private int secondNumber;   // 第二个操作数
    private char operator;      // 运算符('+'或'-')
    private int answer;         // 正确答案
    
    public Exercise(int firstNumber, int secondNumber, char operator) {
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
        this.operator = operator;
        calculateAnswer();
    }
    
    private void calculateAnswer() {
        if (operator == '+') {
            this.answer = firstNumber + secondNumber;
        } else if (operator == '-') {
            this.answer = firstNumber - secondNumber;
        }
    }
    
    public int getFirstNumber() {
        return firstNumber;
    }
    
    public int getSecondNumber() {
        return secondNumber;
    }
    
    public char getOperator() {
        return operator;
    }
    
    public int getAnswer() {
        return answer;
    }
    
    @Override
    public String toString() {
        return firstNumber + " " + operator + " " + secondNumber + " = " + answer;
    }
    
    /**
     * 获取不包含答案的算式字符串
     */
    public String toQuestionString() {
        return firstNumber + " " + operator + " " + secondNumber + " = ";
    }
    
    /**
     * 获取用于判断唯一性的键字符串
     * 对于加法，考虑交换律（如 2+3 和 3+2 视为相同算式）
     */
    public String getUniqueKey() {
        if (operator == '+') {
            // 加法交换律，确保较小的数在前
            int a = Math.min(firstNumber, secondNumber);
            int b = Math.max(firstNumber, secondNumber);
            return a + "+" + b;
        } else {
            // 减法不考虑交换律
            return firstNumber + "-" + secondNumber;
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Exercise exercise = (Exercise) obj;
        return this.getUniqueKey().equals(exercise.getUniqueKey());
    }
    
    @Override
    public int hashCode() {
        return getUniqueKey().hashCode();
    }
}

/**
 * 习题生成器：负责生成指定数量的不重复算术题，并可控制加减法比例
 */
class ExerciseGenerator {
    private Random random = new Random();
    private static final int MAX_NUMBER = 100;  // 最大数字限制
    
    /**
     * 生成指定数量的不重复习题，并控制加减法比例
     * @param count 习题数量
     * @param additionRatio 加法题的比例（0.0-1.0）
     * @return 生成的习题数组
     */
    public Exercise[] generateUniqueExercises(int count, double additionRatio) {
        Exercise[] exercises = new Exercise[count];
        Set<String> uniqueExercises = new HashSet<>();
        
        int additionCount = (int) Math.round(count * additionRatio);
        int subtractionCount = count - additionCount;
        
        // 先生成指定数量的加法题
        while (uniqueExercises.size() < additionCount) {
            Exercise exercise = generateSingleExercise('+');
            String key = exercise.getUniqueKey();
            if (!uniqueExercises.contains(key)) {
                uniqueExercises.add(key);
                exercises[uniqueExercises.size() - 1] = exercise;
            }
        }
        
        // 再生成指定数量的减法题
        while (uniqueExercises.size() < count) {
            Exercise exercise = generateSingleExercise('-');
            String key = exercise.getUniqueKey();
            if (!uniqueExercises.contains(key)) {
                uniqueExercises.add(key);
                exercises[uniqueExercises.size() - 1] = exercise;
            }
        }
        
        // 打乱习题顺序
        shuffleArray(exercises);
        
        return exercises;
    }
    
    /**
     * 生成一道指定类型的习题
     * @param operator 运算符('+'或'-')
     * @return 生成的习题
     */
    private Exercise generateSingleExercise(char operator) {
        int firstNumber, secondNumber;
        
        if (operator == '+') {
            // 加法：两个数都小于100，和也小于100
            firstNumber = random.nextInt(MAX_NUMBER);
            secondNumber = random.nextInt(MAX_NUMBER - firstNumber);
        } else {
            // 减法：确保结果非负
            secondNumber = random.nextInt(MAX_NUMBER / 2);
            firstNumber = secondNumber + random.nextInt(MAX_NUMBER - secondNumber);
        }
        
        return new Exercise(firstNumber, secondNumber, operator);
    }
    
    /**
     * 打乱数组顺序
     * @param array 要打乱的数组
     */
    private void shuffleArray(Exercise[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            int j = random.nextInt(i + 1);
            // 交换元素
            Exercise temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }
}

/**
 * 习题输出器：负责将习题格式化输出
 */
class ExercisePrinter {
    /**
     * 打印所有习题及答案
     * @param exercises 习题数组
     */
    public void printExercisesWithAnswers(Exercise[] exercises) {
        // 每行显示4道题，优化布局
        int exercisesPerLine = 4;
        
        for (int i = 0; i < exercises.length; i++) {
            // 格式化输出，确保对齐
            System.out.printf("(%2d) %-20s", (i + 1), exercises[i].toString());
            
            // 每exercisesPerLine道题换行
            if ((i + 1) % exercisesPerLine == 0) {
                System.out.println();
            }
        }
        
        // 确保最后一行正确结束
        if (exercises.length % exercisesPerLine != 0) {
            System.out.println();
        }
    }
    
    /**
     * 打印所有习题（不显示答案）
     * @param exercises 习题数组
     */
    public void printExercises(Exercise[] exercises) {
        // 每行显示6道题，更密集的布局
        int exercisesPerLine = 6;
        
        for (int i = 0; i < exercises.length; i++) {
            System.out.printf("(%2d) %-15s", (i + 1), exercises[i].toQuestionString());
            
            // 每exercisesPerLine道题换行
            if ((i + 1) % exercisesPerLine == 0) {
                System.out.println();
            }
        }
    }
}